home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / fontOp.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  7KB  |  277 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <X11/cursorfont.h>
  18. #include <X11/Xos.h>
  19. #include <X11/Xatom.h>
  20. #include "xpaint.h"
  21. #include "Paint.h"
  22. #include "misc.h"
  23.  
  24. static Atom    targetAtom, selectionAtom;
  25.  
  26. #define    DELAY    500
  27.  
  28. typedef struct {
  29.     XtIntervalId    id;
  30.     Boolean        typing;
  31.     Boolean        state;
  32.     int        startX, startY, curX, curY, height;
  33.     XFontStruct    *fi;
  34.     int        insertX, insertY, insertSX, insertSY, insertH;
  35.     int        zoom;
  36.     Widget        w;
  37.     char        *sptr;
  38.     int        maxStrLen;
  39.     char        minPos;
  40.     char        *str;
  41.     Drawable    drawable;
  42.     GC        gc, gcx;
  43. } LocalInfo;
  44.  
  45. static void    addString(Widget,LocalInfo*,int,char*);
  46.  
  47. static void    cursor(LocalInfo *l, Boolean flag)
  48. {
  49.     if (l->w == None)
  50.         return;
  51.     if (flag) {
  52.         XDrawLine(XtDisplay(l->w), XtWindow(l->w), l->gcx,
  53.                 l->insertX, l->insertY, l->insertX, l->insertY + l->insertH);
  54.         l->state = !l->state;
  55.     } else if (l->state) {
  56.         XDrawLine(XtDisplay(l->w), XtWindow(l->w), l->gcx,
  57.                 l->insertX, l->insertY, l->insertX, l->insertY + l->insertH);
  58.         l->state = False;
  59.     }
  60. }
  61.  
  62. static void    flash(LocalInfo *l)
  63. {
  64.     cursor(l, True);
  65.     l->id = XtAppAddTimeOut(XtWidgetToApplicationContext(l->w), 
  66.                 DELAY, (XtTimerCallbackProc)flash, (XtPointer)l);
  67. }
  68.  
  69. static void    gotSelection(Widget w, LocalInfo *l, Atom *selection, Atom *type,
  70.                 XtPointer value, unsigned long *len, int *format)
  71. {
  72.     if (!l->typing)
  73.         return;
  74.  
  75.     if (len == 0 || value == NULL)
  76.         return;
  77.  
  78.     switch (*type) {
  79.     case XA_STRING:
  80.         addString(w, l, *len, (char*)value);
  81.         break;
  82.     }
  83.     XtFree((XtPointer)value);
  84. }
  85.  
  86. static void    press(Widget w, LocalInfo *l, XButtonEvent *event, OpInfo *info) 
  87. {
  88.     if (event->button == Button1) {
  89.         cursor(l, False);
  90.  
  91.         XtVaGetValues(w, XtNfont, &l->fi, NULL);
  92.         if (l->fi == NULL)
  93.             return;
  94.  
  95.         l->w      = w;
  96.         l->height = l->fi->ascent + l->fi->descent;
  97.         l->startX = l->curX = info->x;
  98.         l->startY = l->curY = info->y;
  99.         l->curY   = l->curY - l->height / 2;
  100.         l->typing = True;
  101.  
  102.         if (info->surface == opWindow) {
  103.             l->insertH  = l->height * info->zoom;
  104.             l->insertY  = event->y - l->insertH / 2;
  105.             l->insertX  = event->x;
  106.             l->insertSX = event->x;
  107.         }
  108.  
  109.         l->sptr = l->str;
  110.  
  111.         if (l->id == (XtIntervalId)NULL)
  112.             flash(l);
  113.  
  114.         l->zoom   = info->zoom;
  115.         l->gc     = info->first_gc;
  116.         l->minPos = 0;
  117.  
  118.         UndoStartPoint(w, info, l->curX, l->curY);
  119.         if (info->surface == opPixmap)
  120.             l->drawable = info->drawable;
  121.     } else if (event->button == Button2) {
  122.         XtGetSelectionValue(w, selectionAtom, targetAtom,
  123.             (XtSelectionCallbackProc)gotSelection, (XtPointer)l, event->time);
  124.     }
  125. }
  126.  
  127. static void    key(Widget w, LocalInfo *l, XKeyEvent *event, OpInfo *info) 
  128. {
  129.     char        buf[21];
  130.     KeySym        keysym;
  131.     int        len;
  132.  
  133.     if (l->w == None)
  134.         return;
  135.  
  136.     if ((len = XLookupString(event, buf, sizeof(buf) - 1, &keysym, NULL)) == 0)
  137.         return;
  138.  
  139.     l->zoom     = info->zoom;
  140.     l->gc       = info->first_gc;
  141.     l->drawable = info->drawable;
  142.     addString(w, l, len, buf);
  143. }
  144.  
  145. static void    addString(Widget w, LocalInfo *l, int len, char *buf)
  146. {
  147.     int        i, width;
  148.     XRectangle      rect;
  149.  
  150.     if (len != 0)
  151.         cursor(l, False);
  152.     for (i = 0; i < len; i++) {
  153.         if (l->sptr == l->str + l->maxStrLen - 5) {
  154.             int    delta = l->sptr - l->str;
  155.             l->maxStrLen += 128;
  156.             l->str = (char*)XtRealloc((XtPointer)l->str, l->maxStrLen);
  157.             l->sptr = l->str + delta;
  158.         }
  159.  
  160.         if (buf[i] == '\n' || buf[i] == '\r') {
  161.             l->curX     = l->startX;
  162.             l->curY    += l->height + 2;
  163.             l->insertX  = l->insertSX;
  164.             l->insertY += l->insertH + 2 * l->zoom;
  165.  
  166.             *l->sptr++ = '\n';
  167.         } else if (buf[i] == 0x08 || buf[i] == 0x7f) {
  168.             if (l->sptr - l->str > l->minPos) {
  169.                 l->sptr--;
  170.                 if (*l->sptr == '\n') {
  171.                     char    *cp;
  172.                     *l->sptr = '\0';
  173.                     if ((cp = strrchr(l->str, '\n')) == NULL)
  174.                         cp = l->str;
  175.                     else
  176.                         cp++;
  177.                     width = XTextWidth(l->fi, cp, strlen(cp));
  178.                     l->curX = l->startX + width;
  179.                     l->curY    -= l->height + 2;
  180.                     l->insertX = (l->startX + width) * l->zoom;
  181.                     l->insertY -= l->insertH + 2 * l->zoom;
  182.                 } else {
  183.                     width = XTextWidth(l->fi, l->sptr, 1);
  184.                     l->curX -= width;
  185.                     l->insertX -= width * l->zoom;
  186.  
  187.                     /*
  188.                     **  Now undraw the character.
  189.                     */
  190.                     XYtoRECT(l->curX, l->curY, l->curX + width, l->curY + l->height, &rect);
  191.                     PwUpdateFromLast(w, &rect);
  192.                 }
  193.             }
  194.         } else {
  195.             if (l->zoom == 1)
  196.                 XDrawString(XtDisplay(w), XtWindow(w), l->gc, 
  197.                     l->curX, l->curY + l->fi->ascent, &buf[i], 1);
  198.             XDrawString(XtDisplay(w), l->drawable, l->gc, 
  199.                     l->curX, l->curY + l->fi->ascent, &buf[i], 1);
  200.             width = XTextWidth(l->fi, &buf[i], 1);
  201.  
  202.             XYtoRECT(l->curX, l->curY, l->curX + width, l->curY + l->height, &rect);
  203.             PwUpdate(w, &rect, False);
  204.  
  205.             l->curX    += width;
  206.             l->insertX += width * l->zoom;
  207.  
  208.             UndoGrow(w, l->curX, l->curY + l->height);
  209.             UndoGrow(w, l->curX, l->curY + l->height);
  210.  
  211.             *l->sptr++ = buf[i];
  212.         }
  213.     }
  214. }
  215.  
  216. /*
  217. **  Those public functions
  218. */
  219. void *FontAdd(Widget w)
  220. {
  221.     static int    inited = False;
  222.     LocalInfo    *l = (LocalInfo*)XtMalloc(sizeof(LocalInfo));
  223.  
  224.     if (!inited) {
  225.         selectionAtom = XA_PRIMARY;
  226.         targetAtom    = XA_STRING;
  227.     }
  228.  
  229.     l->id = (XtIntervalId)NULL;
  230.     l->w  = None;
  231.     l->typing = False;
  232.     l->state = False;
  233.  
  234.     l->maxStrLen = 128;
  235.     l->str = (char*)XtMalloc(l->maxStrLen);
  236.     l->gcx = GetGCX(w);
  237.  
  238.     OpAddEventHandler(w, opPixmap|opWindow, ButtonPressMask, FALSE, (OpEventProc)press, l);
  239.     OpAddEventHandler(w, opPixmap, KeyPressMask, FALSE, (OpEventProc)key, l);
  240.  
  241.     SetIBeamCursor(w);
  242.  
  243.     return l;
  244. }
  245. void FontRemove(Widget w, LocalInfo *l)
  246. {
  247.     OpRemoveEventHandler(w, opPixmap|opWindow, ButtonPressMask, FALSE, (OpEventProc)press, l);
  248.     OpRemoveEventHandler(w, opPixmap, KeyPressMask, FALSE, (OpEventProc)key, l);
  249.  
  250.     if (l->id != (XtIntervalId)NULL)
  251.         XtRemoveTimeOut(l->id);
  252.  
  253.     cursor(l, False);
  254.  
  255.     XtFree((XtPointer)l->str);
  256.     XtFree((XtPointer)l);
  257. }
  258. void FontChanged(Widget w)
  259. {
  260.     LocalInfo    *l;
  261.  
  262.     if ((int)CurrentOp[0] != (int)FontAdd)
  263.         return;
  264.  
  265.     l = (LocalInfo*)GraphicGetData(w);
  266.     
  267.     XtVaGetValues(w, XtNfont, &l->fi, NULL);
  268.     if (l->fi == NULL)
  269.         return;
  270.  
  271.     cursor(l, False);
  272.     l->height = l->fi->ascent + l->fi->descent;
  273.  
  274.     l->minPos = l->sptr - l->str;
  275.     l->insertH  = l->height * l->zoom;
  276. }
  277.